package controllers

import (
	"crypto/rand"

	"encoding/hex"
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

const uploadDir = "uploads"

// ensureUploadDir 确保上传目录存在
func ensureUploadDir() error {
	if _, err := os.Stat(uploadDir); os.IsNotExist(err) {
		if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
			return fmt.Errorf("failed to create upload directory: %v", err)
		}
	}
	return nil
}

// generateRandomString 生成 6 位随机字符串
func generateRandomString(length int) string {
	bytes := make([]byte, length)
	if _, err := rand.Read(bytes); err != nil {
		return "abcdef" // 备用默认值
	}
	return hex.EncodeToString(bytes)[:length]
}

// generateFileName 使用时间戳 + 6 位随机字符串 + 原始扩展名
func generateFileName(originalName string) string {
	timestamp := time.Now().Unix()
	randomStr := generateRandomString(6)
	ext := filepath.Ext(originalName)
	if ext == "" {
		ext = ".bin" // 默认后缀
	}
	return fmt.Sprintf("%d%s%s", timestamp, randomStr, ext)
}

func UploadFile(c *gin.Context) {
	if err := ensureUploadDir(); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	file, header, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to get file"})
		return
	}
	defer file.Close()

	// 生成时间戳 + 随机字符串的文件名
	hashedFileName := generateFileName(header.Filename)
	filePath := filepath.Join(uploadDir, hashedFileName)

	outFile, err := os.Create(filePath)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save file"})
		return
	}
	defer outFile.Close()

	if _, err := io.Copy(outFile, file); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to write file"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "File uploaded successfully", "fileId": hashedFileName})
}

func DownloadFile(c *gin.Context) {
	fileId := c.Query("fileId")
	if fileId == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Missing fileId"})
		return
	}

	filePath := filepath.Join(uploadDir, fileId)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		c.JSON(http.StatusNotFound, gin.H{"error": "File not found"})
		return
	}

	c.FileAttachment(filePath, fileId)
}
